package com.gmcloud.common.security.config.oauth2;

import cn.hutool.core.util.ReUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.gmcloud.common.security.annotation.Inner;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.*;
import java.util.regex.Pattern;

/**
 * @author zl.sir
 * @version 1.0
 * @since 2021/1/25 13:10
 */

@ConfigurationProperties(prefix = "security.oauth2")
@Component
public class PermitAllUrlProperties implements InitializingBean {
    /**
     * 不需要拦截的地址,白名单
     */
    private Ignore ignore;


    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)}");

    private static final String[] DEFAULT_IGNORE_URLS = new String[]{"/error", "/v3/api-docs","/webjars/**"};



    public PermitAllUrlProperties(Ignore ignore) {
        this.ignore = ignore;
    }

    public PermitAllUrlProperties() {

    }

    public Ignore getIgnore() {
        return ignore;
    }

    public void setIgnore(Ignore ignore) {
        this.ignore = ignore;
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        ignore.getPattern().addAll(Arrays.asList(DEFAULT_IGNORE_URLS));

        RequestMappingHandlerMapping mapping = SpringUtil.getBean("requestMappingHandlerMapping");
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        map.keySet().forEach(info -> {
            HandlerMethod handlerMethod = map.get(info);

            // 获取方法上边的注解 替代path variable 为 *
            // 这个根据springboot版本不一致可能导致info.getPatternsCondition()为null，那就看pathPatternsCondition
            Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class);
            Optional.ofNullable(method).ifPresent(inner ->
                    Objects.requireNonNull(info.getPatternsCondition())
                            .getPatterns().forEach(url -> ignore.getPattern().add(ReUtil.replaceAll(url, PATTERN, "*"))));

//            // 获取类上边的注解, 替代path variable 为 *
            Inner controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Inner.class);
            Optional.ofNullable(controller).ifPresent(inner -> Objects.requireNonNull(info.getPatternsCondition())
                    .getPatterns().forEach(url -> ignore.getPattern().add(ReUtil.replaceAll(url, PATTERN, "*"))));
        });
    }



}
